<?php

namespace App\Library\wxOpen;

use App\Http\Config\ErrorCode;
use App\Library\UpTools;
use App\Models\Saas\Setting;
use App\Models\video\CommonServer;
use App\Models\video\DataCacheModel;

/** 微信第三方平台接口调用 */
class WxOpenUtil
{
    private $appId;
    private $appSecret;
    private $returnData;
    public $mall_id = 0;
    static $object;

    /**
     * WxOpenUtil constructor.
     * @throws \Exception
     */
    public function __construct()
    {
        // 微信第三方平台获取的appId和appSecret
        $wxaOpenConf = Setting::getFields("open_app_id,open_app_secret");
        if(empty($wxaOpenConf['openAppId']) || empty($wxaOpenConf["openAppSecret"])){
            throw new \Exception("微信第三方平台未配置");
        }
        $this->appId = $wxaOpenConf['openAppId'];
        $this->appSecret = $wxaOpenConf["openAppSecret"];
    }

    /**
     * @return WxOpenUtil
     */
    public static function getInstance(){
        if(empty(self::$object)){
            self::$object = new self();
        }
        self::$object->returnData = ErrorCode::code("success");
        return self::$object;
    }

    // 获取令牌
    public function getAccessToken(){
        if($token = cache("componentAccessToken_{$this->appId}")){
            return $token;
        }
        $tempId = request()->mallData["id"];
        request()->mallData = ["id" => 0];
        $componentVerifyTicket = DataCacheModel::getValue("ComponentVerifyTicket_{$this->appId}");
        request()->mallData = ["id" => $tempId];
        if (empty($componentVerifyTicket)) {
            $this->returnData = ErrorCode::code("fail");
            $this->returnData["msg"] = "系统没有component_verify_ticket票据，请稍后再试";
            return $this->returnData;
        }
        $postData = ["component_appid" => $this->appId, "component_appsecret" => $this->appSecret, "component_verify_ticket" => $componentVerifyTicket];
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["api_component_token"], json_encode($postData)), true);
        if(!isset($result["errcode"])){
            cache("componentAccessToken_{$this->appId}", $result["component_access_token"], $result["expires_in"]);
            return $result["component_access_token"];
        }else{
            UpTools::writeLog("结果 -- $componentVerifyTicket--：" . var_export($result, true), "wxOpenLog/getAccessToken.txt");
            $this->returnData = ErrorCode::code("fail");
            $this->returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? "获取令牌失败";
            return $this->returnData;
        }
    }

    // 获取预授权码
    public function getAuthCode(){
        if($code = cache("preAuthCode_{$this->appId}")){
            return $code;
        }
        $componentAccessToken = $this->getAccessToken();
        if(isset($componentAccessToken["code"])){
            return $componentAccessToken;
        }
        $postData = ["component_appid" => $this->appId];
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["api_create_preAuthCode"]."?component_access_token={$componentAccessToken}", json_encode($postData)),true);
        if(!isset($result["errcode"])){
            cache("preAuthCode_{$this->appId}", $result["pre_auth_code"], $result["expires_in"]);
            return $result["pre_auth_code"];
        }else{
            UpTools::writeLog("结果：" . var_export($result, true), "wxOpenLog/getAuthCode.txt");
            $this->returnData = ErrorCode::code("fail");
            $this->returnData["msg"] = "获取预授权码失败：".WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
            return $this->returnData;
        }
    }

    // 获取授权地址
    public function getAuthorizationUrl($redirectUrl = '', $appId = ''){
        $code = $this->getAuthCode();
        if(isset($code["code"])){
            return $code;
        }
        cache("preAuthCode_{$this->appId}", null); // 使用了就去除，下次重新获取新的
        $url = WeChatApi::$weChat_conf["component_login_page"] . "?component_appid={$this->appId}&pre_auth_code={$code}&redirect_uri=".urlencode($redirectUrl);
        if(!empty($appId)){
            $url .= "&biz_appid=".$appId;
        }
        return $url;
    }

    // 使用授权码获取授权信息
    public function getQueryAuth($authCode){
        $componentAccessToken = $this->getAccessToken();
        if (isset($componentAccessToken["code"])) {
            return $componentAccessToken;
        }
        $postData = ["component_appid" => $this->appId, "authorization_code" => $authCode];
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["api_query_auth"]."?component_access_token={$componentAccessToken}", json_encode($postData)), true);
        if(!isset($result["errcode"])){
            DataCacheModel::saveCache(["key" => "authorizer_access_token_{$result["authorization_info"]["authorizer_appid"]}", "value" => $result["authorization_info"]["authorizer_access_token"], "time" => $result["authorization_info"]["expires_in"], "mall_id" => 0]);
            DataCacheModel::saveCache(["key" => "authorizer_refresh_token_{$result["authorization_info"]["authorizer_appid"]}", "value" => $result["authorization_info"]["authorizer_refresh_token"], "time" => 86400 * 29, "mall_id" => 0]);
            return $result["authorization_info"];
        }else{
            UpTools::writeLog("结果 ：" . var_export($result, true), "wxOpenLog/getQueryAuth.txt");
            $this->returnData = ErrorCode::code("fail");
            $this->returnData["msg"] = "获取授权信息失败";
            return $this->returnData;
        }
    }

    // 获取/刷新接口调用令牌token
    public function getRefreshToken($authAppId){
        $tempId = request()->mallData["id"];
        request()->mallData = ["id" => 0];
        $refreshToken = DataCacheModel::getValue("authorizer_refresh_token_{$authAppId}");
        request()->mallData = ["id" => $tempId];
        if (!empty($refreshToken)) {
            $componentAccessToken = $this->getAccessToken();
            if (isset($componentAccessToken["code"])) {
                return $componentAccessToken;
            }
            $postData = ["component_appid" => $this->appId, "authorizer_appid" => $authAppId, "authorizer_refresh_token" => $refreshToken];
            $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["api_authorizer_token"]."?component_access_token={$componentAccessToken}", json_encode($postData)), true);
            if(!isset($result["errcode"])){
                DataCacheModel::saveCache(["key" => "authorizer_access_token_{$authAppId}", "value" => $result["authorizer_access_token"], "time" => $result["expires_in"], "mall_id" => 0]);
                DataCacheModel::saveCache(["key" => "authorizer_refresh_token_{$authAppId}", "value" => $result["authorizer_refresh_token"], "time" => 86400 * 29, "mall_id" => 0]);
                return $result["authorizer_access_token"];
            }else{
                UpTools::writeLog("结果：" . var_export($result, true), "wxOpenLog/getRefreshToken.txt");
                $this->returnData = ErrorCode::code("fail");
                $this->returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
            }
        }else{
            $this->returnData = ErrorCode::code("fail");
            $this->returnData["msg"] = "刷新接口调用令牌不存在，可能小程序未授权";
        }
        return $this->returnData;
    }

    // 获取授权方的帐号基本信息
    public function getAuthorizerInfo($authAppId){
        $componentAccessToken = $this->getAccessToken();
        if (isset($componentAccessToken["code"])) {
            return $componentAccessToken;
        }
        $postData = ["component_appid" => $this->appId, "authorizer_appid" => $authAppId,];
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["api_get_authorizer_info"]."?component_access_token={$componentAccessToken}", json_encode($postData)), true);
        if(!isset($result["errcode"])){
            return $result;
        }else{
            UpTools::writeLog("结果：" . var_export($result, true), "wxOpenLog/getAuthorizerInfo.txt");
            $this->returnData["code"] = $result["errcode"];
            $this->returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
            return $this->returnData;
        }
    }

    // 拉取当前所有已授权的帐号基本信息。
    public function getAuthorizerList($data){
        $componentAccessToken = $this->getAccessToken();
        if (isset($componentAccessToken["code"])) {
            return $componentAccessToken;
        }
        $postData["component_appid"] =  $this->appId;
        $postData["offset"] =  $data['offset'];
        $postData["count"] =  $data['count'];
        return json_decode(UpTools::curl(WeChatApi::$weChat_conf["api_get_authorizer_list"]."?component_access_token={$componentAccessToken}", json_encode($postData)), true);
    }

    // 获取接口访问令牌
    public function getAuthAccessToken($authAppId){
        $tempId = request()->mallData["id"];
        request()->mallData = ["id" => 0];
        $accessToken = DataCacheModel::getValue("authorizer_access_token_{$authAppId}");
        request()->mallData = ["id" => $tempId];
        if(empty($accessToken)) {
            $accessToken = $this->getRefreshToken($authAppId);
        }
        return $accessToken;
    }

    // 设置服务器域名
    public function modifyDomain($authAppId, $postData = [], $type = "add"){
        $accessToken = $this->getAuthAccessToken($authAppId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        if(empty($postData)) {
            $postData = [
                "action" => $type, "requestdomain" => [request()->getSchemeAndHttpHost()], "wsrequestdomain" => ["wss://".request()->getHttpHost()], "uploaddomain" => [request()->getSchemeAndHttpHost()], "downloaddomain" => [request()->getSchemeAndHttpHost()],
            ];
        }
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["modify_domain"]."?access_token={$accessToken}", json_encode($postData)), true);
        if($result["errcode"] != "0") {
            $returnData["code"] = $result["errcode"];
            $returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
            UpTools::writeLog("结果：" . var_export($result, true) . var_export($postData, true), "wxOpenLog/modifyDomain.txt");
            return $returnData;
        }
        return $this->returnData;
    }

    // 设置业务域名
    public function setWebViewDomain($authAppId, $postData = []){
        $accessToken = $this->getAuthAccessToken($authAppId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        if(empty($postData)) {
            $postData = ["action" => "add", "webviewdomain" => [CommonServer::getUrl()]];
        }
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["set_web_view_domain"]."?access_token={$accessToken}", json_encode($postData)), true);
        if($result["errcode"] != "0") {
            $returnData = ErrorCode::code("fail");
            $returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
            UpTools::writeLog("结果：" . var_export($result, true), "wxOpenLog/setWebViewDomain.txt");
            return $returnData;
        }
        return $this->returnData;
    }

    // 获取已设置的所有类目
    public function getCategories($authAppId){
        $accessToken = $this->getAuthAccessToken($authAppId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["get_category"]."?access_token={$accessToken}"), true);
        if($result["errcode"] != "0") {
            $this->returnData = ErrorCode::code("fail");
            $this->returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
            UpTools::writeLog("结果：" . var_export($result, true), "wxOpenLog/getCategories.txt");
        }else{
            $this->returnData = $result;
        }
        return $this->returnData;
    }

    // 获取可设置的所有类目
    public function getAllCategories($authAppId){
        $accessToken = $this->getAuthAccessToken($authAppId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["get_all_categories"]."?access_token={$accessToken}"), true);

        if($result["errcode"] == "0"){
            $this->returnData["data"] = $result["categories_list"]["categories"];
        }else{
            $this->returnData = ErrorCode::$errorCode["fail"];
            $this->returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
            UpTools::writeLog("结果：" . var_export($result, true), "wxOpenLog/getAllCategories.txt");
        }
        return $this->returnData;
    }

    // 获取代码模板列表
    public function getTemplateList(){
        $componentAccessToken = $this->getAccessToken();
        if (isset($componentAccessToken["code"])) {
            return $componentAccessToken;
        }
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["get_template_list"]."?access_token={$componentAccessToken}"), true);

        if($result["errcode"] == "0"){
            $this->returnData["data"] = $result["template_list"];
        }else{
            $this->returnData = ErrorCode::$errorCode["fail"];
            $this->returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
            UpTools::writeLog("结果：" . var_export($result, true), "wxOpenLog/getTemplateList.txt");
        }
        return $this->returnData;
    }

    // 上传小程序代码
    public function uploadCommit($data, $params){
        if(empty($data)){
            return ErrorCode::$errorCode["fail"];
        }
        $accessToken = $this->getAuthAccessToken($data["appId"]);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        $salt = UpTools::generateSalt($params["id"]); // 域名前缀，唯一值
        if(strpos(request()->getSchemeAndHttpHost(), SystemConfig::PRODUCT_ENV_DOMAIN) !== false) { // 生产环境
            $domain = SystemConfig::$tcDomain_conf["product"]["domainPrefix"] . "-{$salt}." . SystemConfig::$tcDomain_conf["product"]["domainName"];
        }else{
            $domain = SystemConfig::$tcDomain_conf["develop"]["domainPrefix"] . "-{$salt}." . SystemConfig::$tcDomain_conf["develop"]["domainName"];
        }
        $res = commonModel::getFields(scfConfigTable, "env,alias", ["instance_id" => $params["id"]]);
        $postData = [
            "template_id" => $data["templateId"],
            "ext_json" => "{\"extEnable\":\"true\",\"ext\":{\"domain\":\"https://".$domain."/release\",\"env\":\"".$res["env"]."\",\"alias\":\"".$res["alias"]."\"}}",
            "user_version" => $data["version"],
            "user_desc" => $data["desc"],
        ];
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["commit"]."?access_token={$accessToken}", json_encode($postData, JSON_UNESCAPED_UNICODE)), true);
        if($result["errcode"] != "0"){
            $this->returnData = ErrorCode::$errorCode["fail"];
            $this->returnData["olderrmsg"] = $result["errmsg"];
            $this->returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
            UpTools::writeLog("结果：" . var_export($result, true), "wxOpenLog/uploadCommit.txt");
        }else{
            $this->returnData["data"] = $result;
            $authResult = $this->getAuthorizerInfo($data["appId"]);
            if(isset($authResult["authorizer_info"]) && !in_array($domain, $authResult["authorizer_info"]["MiniProgramInfo"]["network"]["RequestDomain"])) {
                $this->modifyDomain($data["appId"], [
                    "action" => "add", "requestdomain" => ["https://{$domain}"], "wsrequestdomain" => ["wss://{$domain}"], "uploaddomain" => ["https://{$domain}"], "downloaddomain" => ["https://{$domain}"]
                ]);
                $this->setWebViewDomain($data["appId"], ["action" => "set", "webviewdomain" => ["https://{$domain}"]]);
            }
        }
        return $this->returnData;
    }

    // 获取小程序页面地址
    public function getPage($authAppId){
        $accessToken = $this->getAuthAccessToken($authAppId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["get_page"]."?access_token={$accessToken}"), true);
        if($result["errcode"] == "0"){
            $this->returnData["data"] = $result["page_list"];
        }else if($result["errcode"] == "86001"){ // "86001"=>"不存在第三方的已经提交的代码"
            $this->returnData["data"] = [];
        }else{
            $this->returnData = ErrorCode::$errorCode["fail"];
            $this->returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
            UpTools::writeLog("结果：" . var_export($result, true), "wxOpenLog/getPage.txt");
        }
        return $this->returnData;
    }

    // 获取的体验版二维码
    public function getQrCode($authAppId){
        $accessToken = $this->getAuthAccessToken($authAppId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        $result = UpTools::curl(WeChatApi::$weChat_conf["get_qrCode"]."?access_token={$accessToken}");
        $res = json_decode($result, true);
        if(!empty($res)){
            UpTools::writeLog("结果：" . var_export($res, true), "wxOpenLog/getQrcode.txt");
            $this->returnData = ErrorCode::$errorCode["fail"];
            $this->returnData["msg"] = isset(WeChatApi::$wxChatCode[$res["errcode"]]) ? WeChatApi::$wxChatCode[$res["errcode"]] : $res["errmsg"];
            return $this->returnData;
        }
        return $result;
    }

    // 提交审核
    public function getSubmitAudit($authAppId, $postData, $instanceId){
        $accessToken = $this->getAuthAccessToken($authAppId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["submit_audit"]."?access_token={$accessToken}", json_encode($postData, JSON_UNESCAPED_UNICODE)), true);
        if($result["errcode"] != "0"){
            $this->returnData = ErrorCode::$errorCode["fail"];
            $this->returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
            UpTools::writeLog("结果：" . var_export($result, true) . var_export($postData, true), "wxOpenLog/getSubmitAudit.txt");
            // 临时处理
            if($result["errcode"] == "85008"){
                $this->returnData["msg"] = "类目设置异常，请修改“小程序信息”配置里的“类目”配置项。";
            }
        }else {
            trThirdData::toSave(2, "wx_mini_{$instanceId}_{$authAppId}"); // 审核中
        }
        return $this->returnData;
    }

    // 查询最新一次提交的审核状态  https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/code/get_latest_auditstatus.html
    public function getLatestAuditStatus($authAppId, $instanceId){
        $accessToken = $this->getAuthAccessToken($authAppId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["get_latest_auditStatus"]."?access_token={$accessToken}", ""), true);
        if($result["errcode"] != "0"){
            $this->returnData = ErrorCode::$errorCode["fail"];
            $this->returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
            UpTools::writeLog("结果：" . var_export($result, true), "wxOpenLog/getLatestAuditStatus.txt");
        }elseif(!empty($result["reason"])){
            $this->returnData["msg"] = "审核失败原因：".$result["reason"];
            UpTools::writeLog("结果：" . var_export($result, true), "wxOpenLog/getLatestAuditStatus.txt");
        }
        if(isset($result["status"])){
            if($result["status"] == "0" && trThirdData::getValues("wx_mini_{$instanceId}_{$authAppId}") == '9') { // 审核成功，审核版本是否发布了
                $result["status"] = 9; // 审核成功并发布了
            }
            $result["statusText"] = $this->auditMsg($result["status"]);
        }
        $this->returnData["data"] = $result;
        return $this->returnData;
    }

    public function auditMsg($status){
        $msg = [
            0 => "审核成功", 1 => "审核被拒绝", 2 => "审核中", 3 => "已撤回", 9 => "审核成功可以发布"
        ];
        return $msg[$status] ?? "";
    }

    // 查询指定发布审核单的审核状态
    public function getAuditStatus($authAppId, $auditId, $instanceId){
        $accessToken = $this->getAuthAccessToken($authAppId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        $data = ["auditid" => $auditId,];
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["get_auditStatus"]."?access_token={$accessToken}", json_encode($data, JSON_UNESCAPED_UNICODE)), true);
        if($result["errcode"] != "0"){
            $this->returnData = ErrorCode::$errorCode["fail"];
            $this->returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
            UpTools::writeLog("结果：" . var_export($result, true), "wxOpenLog/getAuditStatus.txt");
        }elseif(!empty($result["reason"])){
            $this->returnData = ErrorCode::$errorCode["fail"];
            $this->returnData["msg"] = "审核被拒绝原因：".$result["reason"];
            UpTools::writeLog("结果：" . var_export($result, true), "wxOpenLog/getAuditStatus.txt");
        }
        if(isset($result["status"])){
            if($result["status"] == "0" && trThirdData::getValues("wx_mini_{$instanceId}_{$authAppId}") == '9') { // 审核成功，审核版本是否发布了
                $result["status"] = 9; // 审核成功并发布了
            }
            $result["statusText"] = $this->auditMsg($result["status"]);
        }
        $this->returnData["data"] = $result;
        return $this->returnData;
    }

    // 发布已通过审核的小程序
    public function releaseMini($authAppId, $instanceId){
        $accessToken = $this->getAuthAccessToken($authAppId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["release"]."?access_token={$accessToken}", "{}"), true);
        if($result["errcode"] != "0"){
            UpTools::writeLog("结果：" . var_export($result, true), "wxOpenLog/releaseMini.txt");
        }
        if($result["errcode"] === 0){ // 审核版本已经发布成功了
            trThirdData::toSave(9, "wx_mini_{$instanceId}_{$authAppId}");
        }
        $this->returnData["data"] = $result;
        return $this->returnData;
    }

    // 小程序审核撤回
    public function undoCodeAudit($authAppId, $instanceId){
        $accessToken = $this->getAuthAccessToken($authAppId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["undo_code_audit"]."?access_token={$accessToken}", ""), true);
        if($result["errcode"] != "0"){
            UpTools::writeLog("结果：" . var_export($result, true), "wxOpenLog/undoCodeAudit.txt");
            $this->returnData = ErrorCode::$errorCode["fail"];
            $this->returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
        }else {
            trThirdData::toSave(2, "wx_mini_{$instanceId}_{$authAppId}"); // 审核中
            $this->returnData["data"] = $result;
        }
        return $this->returnData;
    }

    /**                              小程序云开发                                  */
    // 第三方平台调用为授权平台云开发权限的帐号开通  https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/cloudbase/creatCloudUser.html
    public function doCreateCloudUser($appId){
        $accessToken = $this->getAuthAccessToken($appId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        $res = json_decode(UpTools::curl(WeChatApi::$weChat_conf["create_cloud_user"]."?access_token={$accessToken}", json_encode([])), true);
        if ($res["errcode"] != "0") {
            $this->returnData = ErrorCode::$errorCode["fail"];
            $this->returnData["msg"] = isset(WeChatApi::$wxChatCode[$res["errcode"]]) ? WeChatApi::$wxChatCode[$res["errcode"]] : $res["errmsg"];
            UpTools::writeLog("结果：" . var_export($res, true), "wxOpenLog/doCreateCloudUser.txt");
        }else{
            $this->returnData["data"] = $res;
        }
        return $this->returnData;
    }

    // 获取云环境信息  https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/cloudbase/getEnvInfo.html
    public function getEnvInfo($appId, $envId = ''){
        $accessToken = $this->getAuthAccessToken($appId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        if(!empty($envId)){
            $params = ["env" => $envId];
        }else{
            $params = new \stdClass();
        }
        $res = json_decode(UpTools::curl(WeChatApi::$weChat_conf["get_env_info"]."?access_token={$accessToken}", json_encode($params)), true);
        if ($res["errcode"] != "0") {
            $this->returnData["code"] = $res["errcode"];
            $this->returnData["msg"] = isset(WeChatApi::$wxChatCode[$res["errcode"]]) ? WeChatApi::$wxChatCode[$res["errcode"]] : $res["errmsg"];
            UpTools::writeLog("结果：" . var_export($res, true) . $envId, "wxOpenLog/getEnvInfo.txt");
        }else{
            $this->returnData["data"] = $res['info_list'];
        }
        return $this->returnData;
    }

    // 创建云环境  https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/cloudbase/createEnvAndResource.html
    public function doCreateEnvAndResource($appId, $data){
        $accessToken = $this->getAuthAccessToken($appId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        if(empty($data)) {
            return ErrorCode::$errorCode["fail"];
        }
        $res = json_decode(UpTools::curl(WeChatApi::$weChat_conf["create_env_and_resource"]."?access_token={$accessToken}", json_encode($data)), true);
        if ($res["errcode"] != "0") {
            $this->returnData["code"] = $res["errcode"];
            $this->returnData["msg"] = isset(WeChatApi::$wxChatCode[$res["errcode"]]) ? WeChatApi::$wxChatCode[$res["errcode"]] : $res["errmsg"];
            UpTools::writeLog("结果：" . var_export($res, true) . var_export($data, true), "wxOpenLog/doCreateEnvAndResource.txt");
        }else{
            $this->returnData["data"] = $res;
        }
        return $this->returnData;
    }

    // 创建云函数 https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/cloudbase/createFunction.html
    public function doCreateFunction($appId, $data){
        $accessToken = $this->getAuthAccessToken($appId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        if(empty($data)) {
            return ErrorCode::$errorCode["fail"];
        }
        $res = json_decode(UpTools::curl(WeChatApi::$weChat_conf["create_function"]."?access_token={$accessToken}", json_encode($data)), true);
        if ($res["errcode"] != "0") {
            $this->returnData["code"] = $res["errcode"];
            $this->returnData["requestParam"] = $data;
            $this->returnData["requestUrl"] = WeChatApi::$weChat_conf["create_function"];
            $this->returnData["msg"] = isset(WeChatApi::$wxChatCode[$res["errcode"]]) ? WeChatApi::$wxChatCode[$res["errcode"]] : $res["errmsg"];
            UpTools::writeLog("结果：" . var_export($res, true) . var_export($data, true), "wxOpenLog/doCreateFunction.txt");
        }else{
            $this->returnData["data"] = $res;
        }
        return $this->returnData;
    }

    // 获取云函数下载地址 https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/cloudbase/downloadFunction.html
    public function downloadFunction($appId, $data){
        $accessToken = $this->getAuthAccessToken($appId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        if(empty($data)) {
            return ErrorCode::$errorCode["fail"];
        }
        $res = json_decode(UpTools::curl(WeChatApi::$weChat_conf["download_function"]."?access_token={$accessToken}", json_encode($data)), true);
        if ($res["errcode"] != "0") {
            $this->returnData["code"] = $res["errcode"];
            $this->returnData["msg"] = isset(WeChatApi::$wxChatCode[$res["errcode"]]) ? WeChatApi::$wxChatCode[$res["errcode"]] : $res["errmsg"];
            UpTools::writeLog("结果：" . var_export($res, true) . var_export($data, true), "wxOpenLog/downloadFunction.txt");
        }else{
            $this->returnData["data"] = $res;
        }
        return $this->returnData;
    }

    // 上传云函数 https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/cloudbase/getUploadSignature.html  https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/cloudbase/updateFunctionCode.html
    public function doCloudUpload($appId, $data){
        $i = 0;
        do {
            $accessToken = $this->getAuthAccessToken($appId);
            if(isset($accessToken["code"])){
                return $accessToken;
            }
            if(empty($data)) {
                return ErrorCode::$errorCode["fail"];
            }
            $postData = json_encode($data, JSON_UNESCAPED_UNICODE);
            $hash = strtolower(bin2hex(hash("sha256", $postData, true)));
            $res = json_decode(UpTools::curl(WeChatApi::$weChat_conf["get_upload_signature"]."?access_token={$accessToken}", json_encode(["hashed_payload" => $hash])), true);
            if($res["errcode"] != '0'){
                UpTools::writeLog("发布小程序云开发：" . var_export($res, true), "wxOpenLog/doCloudUpload.txt");
                $this->returnData = ErrorCode::$errorCode["fail"];
                $this->returnData["msg"] = isset(WeChatApi::$wxChatCode[$res["errcode"]]) ? WeChatApi::$wxChatCode[$res["errcode"]] : $res["errmsg"];
                return $this->returnData;
            }
            $result = json_decode(UpTools::curl(TenCentApi::$tcCloud_conf["scf"]["apiUrl"], $postData, explode("\r\n", $res["headers"])), true);
            $i++;
        }while($i <=5 && isset($result["Response"]["Error"]["Code"]) && $result["Response"]["Error"]["Code"] == "FailedOperation.UpdateFunctionCode" && sleep(0.5));
        if (isset($result["Response"]["Error"])) {
            UpTools::writeLog("发布小程序云开发--：" . var_export($result, true), "wxOpenLog/doCloudUpload.txt");
            $this->returnData = ErrorCode::$errorCode["fail"];
            $this->returnData["msg"] = $result["Response"]["Error"]["Code"] == "ResourceNotFound.Namespace" ? "环境ID：{$data["Namespace"]}不存在" : $result["Response"]["Error"]["Message"];
            $this->returnData["error"] = $result;
        }else{
            $this->returnData = ErrorCode::$errorCode["success"];
            $this->returnData["data"] = $result["Response"];
        }
        return $this->returnData;
    }

    // 创建数据集
    public function createCloudCollection($appId, $data){
        $accessToken = $this->getAuthAccessToken($appId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        if(empty($data)) {
            return ErrorCode::$errorCode["fail"];
        }
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["database_collection_add"]."?access_token={$accessToken}", json_encode($data)), true);
        if($result["errcode"] != "0") {
            $this->returnData["code"] = $result["errcode"];
            $this->returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
            UpTools::writeLog("结果：" . var_export($result, true) . var_export($data, true), "wxOpenLog/createCloudCollection.txt");
        }else{
            $this->returnData["data"] = $result;
        }
        return $this->returnData;
    }

    // 上传云函数配置 https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/cloudbase/uploadFuncConfig.html
    public function doUploadFuncConfig($appId, $data){
        $accessToken = $this->getAuthAccessToken($appId);
        if(isset($accessToken["code"])){
            return $accessToken;
        }
        if(empty($data)) {
            return ErrorCode::$errorCode["fail"];
        }
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["upload_func_config"]."?access_token={$accessToken}", json_encode($data, JSON_UNESCAPED_UNICODE)), true);
        if($result["errcode"] != "0") {
            $this->returnData["code"] = $result["errcode"];
            $this->returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
            UpTools::writeLog("结果：" . var_export($result, true) . var_export($data, true), "wxOpenLog/doUploadFuncConfig.txt");
        }else{
            $this->returnData["data"] = $result;
        }
        return $this->returnData;
    }

    /**                小程序认证                   */
    // 提交创建小程序的申请
    public function toSubmitCreateMini($data){
        foreach (["name" => "企业名", "code" => "企业代码", "codeType" => "企业代码类型", "legalWechat" => "法人微信号", "legalName" => "法人姓名", "componentPhone" => "第三方联系电话"] as $f => $msg){
            if(empty($data[$f])){
                return ErrorCode::code("params_not_exist", $msg);
            }
        }
        $componentAccessToken = $this->getAccessToken();
        if (isset($componentAccessToken["code"])) {
            return $componentAccessToken;
        }
        $postData = [
            "name" => $data["name"], "code" => $data["code"], "code_type" => $data["codeType"], "legal_persona_wechat" => $data["legalWechat"],
            "legal_persona_name" => $data["legalName"], "component_phone" => $data["componentPhone"]
        ];
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["fast_register_weApp"]."?action=create&component_access_token={$componentAccessToken}", json_encode($postData, JSON_UNESCAPED_UNICODE)), true);
        if($result["errcode"] != "0"){
            UpTools::writeLog("结果：" . var_export($result, true) . var_export(json_encode($postData, JSON_UNESCAPED_UNICODE), true), "wxOpenLog/toSubmitCreateMini.txt");
        }
        $this->returnData["code"] = $result["errcode"];
        $this->returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
        $this->returnData["data"] = $result;
        return $this->returnData;
    }

    // 查询创建任务状态
    public function getSearchMiniStatus($data){
        foreach (["name" => "企业名", "legalWechat" => "法人微信号", "legalName" => "法人姓名"] as $f => $msg){
            if(empty($data[$f])){
                return ErrorCode::code("params_not_exist", $msg);
            }
        }
        $componentAccessToken = $this->getAccessToken();
        if (isset($componentAccessToken["code"])) {
            return $componentAccessToken;
        }
        $postData = ["name" => $data["name"], "legal_persona_wechat" => $data["legalWechat"], "legal_persona_name" => $data["legalName"]];
        $result = json_decode(UpTools::curl(WeChatApi::$weChat_conf["fast_register_weApp"]."?action=search&component_access_token={$componentAccessToken}", json_encode($postData, JSON_UNESCAPED_UNICODE)), true);
        if($result["errcode"] != "0"){
            UpTools::writeLog("结果：" . var_export($result, true) . var_export(json_encode($postData, JSON_UNESCAPED_UNICODE), true), "wxOpenLog/getSearchMiniStatus.txt");
        }
        $this->returnData["code"] = $result["errcode"];
        $this->returnData["msg"] = WeChatApi::$wxChatCode[$result["errcode"]] ?? $result["errmsg"];
        $this->returnData["data"] = $result;
        return $this->returnData;
    }
}